/*
 * Copyright (c) 2025 Industrial Software Feature Database
 */
package com.comac.ins.isfd.service.impl;

import cn.hutool.core.date.DateTime;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.StringUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.comac.ins.common.core.domain.model.LoginUser;
import com.comac.ins.common.core.exception.base.BaseException;
import com.comac.ins.common.core.utils.MapstructUtils;
import com.comac.ins.common.mybatis.core.page.PageQuery;
import com.comac.ins.common.mybatis.core.page.TableDataInfo;
import com.comac.ins.isfd.constant.enums.IsfdDatabaseModelSpecialFieldNameEnum;
import com.comac.ins.isfd.constant.enums.IsfdImportMethodEnum;
import com.comac.ins.isfd.domain.IsfdDatabaseDataImportRecord;
import com.comac.ins.isfd.domain.IsfdDatabaseDataImportSubRecord;
import com.comac.ins.isfd.domain.IsfdDatabaseModelConfig;
import com.comac.ins.isfd.domain.IsfdDatabaseMongoQuery;
import com.comac.ins.isfd.domain.bo.IsfdDatabaseDataImportRecordBo;
import com.comac.ins.isfd.domain.bo.IsfdDatabaseDataImportSubRecordBo;
import com.comac.ins.isfd.domain.bo.query.IsfdDatabaseDataImportRecordQueryBo;
import com.comac.ins.isfd.domain.vo.IsfdBusinessDatabaseRefWithNameVo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseDataImportRecordListVo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseDataImportRecordVo;
import com.comac.ins.isfd.domain.vo.IsfdDatabaseModelConfigVo;
import com.comac.ins.isfd.mapper.IsfdBusinessDatabaseRefMapper;
import com.comac.ins.isfd.mapper.IsfdDatabaseDataImportRecordMapper;
import com.comac.ins.isfd.mapper.IsfdDatabaseDataImportSubRecordMapper;
import com.comac.ins.isfd.mapper.IsfdDatabaseModelConfigMapper;
import com.comac.ins.isfd.service.IIsfdDatabaseDataImportRecordService;
import com.comac.ins.isfd.service.IIsfdDatabaseDataImportSubRecordService;
import com.comac.ins.isfd.service.IIsfdDatabaseModelConfigService;
import com.comac.ins.isfd.service.IIsfdDatabaseMongoService;
import com.comac.ins.system.domain.vo.SysUserVo;
import com.comac.ins.system.service.ISysUserService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import java.util.*;

/**
 * 数据导入记录Service业务层处理
 *
 * @author Lion Li
 * @date 2024-12-06
 */
@RequiredArgsConstructor
@Service
@Slf4j
public class IsfdDatabaseDataImportRecordServiceImpl implements IIsfdDatabaseDataImportRecordService {

    private final IsfdDatabaseDataImportRecordMapper baseMapper;

    private final IsfdDatabaseDataImportSubRecordMapper isfdDatabaseDataImportSubRecordMapper;

    @Autowired
    private ISysUserService iSysUserService;

    @Autowired
    private IIsfdDatabaseDataImportSubRecordService importSubRecordService;

    @Autowired
    private IIsfdDatabaseMongoService mongoService;

    @Autowired
    IsfdDatabaseModelConfigMapper isfdDatabaseModelConfigMapper;

    @Autowired
    IIsfdDatabaseModelConfigService isfdDatabaseModelConfigService;

    @Autowired
    IsfdBusinessDatabaseRefMapper isfdBusinessDatabaseRefMapper;

    /**
     * 查询数据导入记录
     *
     * @param id 主键
     * @return 数据导入记录
     */
    @Override
    public IsfdDatabaseDataImportRecordVo queryById(Long id) {
        return baseMapper.selectVoById(id);
    }

    @Override
    public TableDataInfo<IsfdDatabaseDataImportRecordListVo> queryPageList(IsfdDatabaseDataImportRecordQueryBo queryBo) {
        PageQuery pageQuery = new PageQuery();
        pageQuery.setPageNum(queryBo.getPageNum());
        pageQuery.setPageSize(queryBo.getPageSize());
        String createUserName = queryBo.getCreateUserName();
        Long createBy = null;
        if (StringUtils.isNotBlank(createUserName)) {
            SysUserVo sysUserVo = iSysUserService.selectUserByUserName(createUserName);
            if (sysUserVo != null) {
                createBy = sysUserVo.getUserId();
            }
        }
        LambdaQueryWrapper<IsfdDatabaseDataImportRecord> lqw = buildQueryWrapper(queryBo, createBy);
        Page<IsfdDatabaseDataImportRecordVo> recordVoPage = baseMapper.selectVoPage(pageQuery.build(), lqw);
        long total = recordVoPage.getTotal();
        if (total == 0) {
            return TableDataInfo.build();
        }
        List<IsfdDatabaseDataImportRecordVo> records = recordVoPage.getRecords();
        List<IsfdDatabaseDataImportRecordListVo> result = MapstructUtils.convert(records, IsfdDatabaseDataImportRecordListVo.class);
        result.forEach(t -> {
            if (t.getCreateBy() != null) {
                SysUserVo sysUserVo = iSysUserService.selectUserById(t.getCreateBy());
                if (sysUserVo != null) {
                    t.setCreateUserName(sysUserVo.getUserName());
                }
            }
        });
        return TableDataInfo.build(result, total);
    }

    /**
     * 分页查询数据导入记录列表
     *
     * @param bo        查询条件
     * @param pageQuery 分页参数
     * @return 数据导入记录分页列表
     */
    @Override
    public TableDataInfo<IsfdDatabaseDataImportRecordVo> queryPageList(IsfdDatabaseDataImportRecordBo bo, PageQuery pageQuery) {
        LambdaQueryWrapper<IsfdDatabaseDataImportRecord> lqw = buildQueryWrapper(bo);
        Page<IsfdDatabaseDataImportRecordVo> result = baseMapper.selectVoPage(pageQuery.build(), lqw);
        return TableDataInfo.build(result);
    }

    /**
     * 查询符合条件的数据导入记录列表
     *
     * @param bo 查询条件
     * @return 数据导入记录列表
     */
    @Override
    public List<IsfdDatabaseDataImportRecordVo> queryList(IsfdDatabaseDataImportRecordBo bo) {
        LambdaQueryWrapper<IsfdDatabaseDataImportRecord> lqw = buildQueryWrapper(bo);
        return baseMapper.selectVoList(lqw);
    }

    private LambdaQueryWrapper<IsfdDatabaseDataImportRecord> buildQueryWrapper(IsfdDatabaseDataImportRecordBo bo) {
        Map<String, Object> params = bo.getParams();
        LambdaQueryWrapper<IsfdDatabaseDataImportRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(bo.getModelId() != null, IsfdDatabaseDataImportRecord::getModelId, bo.getModelId());
        lqw.like(StringUtils.isNotBlank(bo.getModelName()), IsfdDatabaseDataImportRecord::getModelName, bo.getModelName());
        lqw.like(StringUtils.isNotBlank(bo.getTableName()), IsfdDatabaseDataImportRecord::getTableName, bo.getTableName());
        lqw.eq(bo.getDataQualityId() != null, IsfdDatabaseDataImportRecord::getDataQualityId, bo.getDataQualityId());
        lqw.eq(bo.getDataConversionId() != null, IsfdDatabaseDataImportRecord::getDataConversionId, bo.getDataConversionId());
        lqw.eq(bo.getDataTemplateId() != null, IsfdDatabaseDataImportRecord::getDataTemplateId, bo.getDataTemplateId());
        lqw.like(StringUtils.isNotBlank(bo.getDataTemplateName()), IsfdDatabaseDataImportRecord::getDataTemplateName, bo.getDataTemplateName());
        lqw.eq(bo.getDataQuantity() != null, IsfdDatabaseDataImportRecord::getDataQuantity, bo.getDataQuantity());
        lqw.eq(StringUtils.isNotBlank(bo.getImportMethod()), IsfdDatabaseDataImportRecord::getImportMethod, bo.getImportMethod());
        lqw.eq(StringUtils.isNotBlank(bo.getDataForm()), IsfdDatabaseDataImportRecord::getDataForm, bo.getDataForm());
        lqw.eq(StringUtils.isNotBlank(bo.getDataFileUrl()), IsfdDatabaseDataImportRecord::getDataFileUrl, bo.getDataFileUrl());
        lqw.eq(bo.getDataImportTime() != null, IsfdDatabaseDataImportRecord::getDataImportTime, bo.getDataImportTime());
        lqw.eq(StringUtils.isNotBlank(bo.getDataImportBy()), IsfdDatabaseDataImportRecord::getDataImportBy, bo.getDataImportBy());
        lqw.eq(StringUtils.isNotBlank(bo.getDataSource()), IsfdDatabaseDataImportRecord::getDataSource, bo.getDataSource());
        lqw.eq(StringUtils.isNotBlank(bo.getComment()), IsfdDatabaseDataImportRecord::getComment, bo.getComment());
        lqw.eq(IsfdDatabaseDataImportRecord::getIsDelete, 0);
        return lqw;
    }

    private LambdaQueryWrapper<IsfdDatabaseDataImportRecord> buildQueryWrapper(IsfdDatabaseDataImportRecordQueryBo queryBo,
                                                                               Long createBy) {
        LambdaQueryWrapper<IsfdDatabaseDataImportRecord> lqw = Wrappers.lambdaQuery();
        lqw.eq(queryBo.getModelId() != null, IsfdDatabaseDataImportRecord::getModelId, queryBo.getModelId());
        lqw.like(StringUtils.isNotBlank(queryBo.getFileName()), IsfdDatabaseDataImportRecord::getFileName, queryBo.getFileName());
        lqw.eq(createBy != null, IsfdDatabaseDataImportRecord::getCreateBy, createBy);
        if (queryBo.getStartCreateTime() != null && queryBo.getEndCreateTime() != null) {
            lqw.between(IsfdDatabaseDataImportRecord::getDataImportTime, queryBo.getStartCreateTime(), queryBo.getEndCreateTime());
        }
        lqw.eq(IsfdDatabaseDataImportRecord::getIsDelete, 0);
        lqw.orderByDesc(IsfdDatabaseDataImportRecord::getCreateTime);
        return lqw;
    }

    /**
     * 新增数据导入记录
     *
     * @param bo 数据导入记录
     * @return 是否新增成功
     */
    @Override
    @Transactional
    public Boolean insertByBo(IsfdDatabaseDataImportRecordBo bo) {
        IsfdDatabaseDataImportRecord add = MapstructUtils.convert(bo, IsfdDatabaseDataImportRecord.class);
        validEntityBeforeSave(add);
        boolean flag = baseMapper.insert(add) > 0;
        if (flag) {
            bo.setId(add.getId());
        }
        return flag;
    }

    /**
     * 修改数据导入记录
     *
     * @param bo 数据导入记录
     * @return 是否修改成功
     */
    @Override
    public Boolean updateByBo(IsfdDatabaseDataImportRecordBo bo) {
        IsfdDatabaseDataImportRecord update = MapstructUtils.convert(bo, IsfdDatabaseDataImportRecord.class);
        validEntityBeforeSave(update);
        return baseMapper.updateById(update) > 0;
    }

    @Override
    public void batchUpdateById(List<IsfdDatabaseDataImportRecordBo> boList) {
        baseMapper.updateBatchById(MapstructUtils.convert(boList, IsfdDatabaseDataImportRecord.class));
    }

    /**
     * 保存前的数据校验
     */
    private void validEntityBeforeSave(IsfdDatabaseDataImportRecord entity) {
        //TODO 做一些数据校验,如唯一约束
    }

    /**
     * 校验并批量删除数据导入记录信息
     *
     * @param ids 待删除的主键集合
     * @return 是否删除成功
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public Boolean deletByIds(Collection<Long> ids) {
        // 删除子表
        importSubRecordService.deleteByRecordIds(ids);

        return baseMapper.deleteBatchIds(ids) > 0;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public IsfdDatabaseDataImportRecordBo createImportRecord(IsfdDatabaseDataImportRecordBo recordBo, IsfdImportMethodEnum importMethodEnum, String mainTableName, Map<String, Integer> tableNameAndDataQuantity, LoginUser loginUser){

        IsfdDatabaseModelConfigVo configVo = isfdDatabaseModelConfigMapper.selectByTableName(mainTableName);
        if (configVo == null) {
            log.error("没有找到数据模型配置，表名：" + mainTableName);
            throw new BaseException("没有找到数据模型配置，表名：" + mainTableName);
        }
        IsfdDatabaseModelConfig topConfig = isfdDatabaseModelConfigService.queryByIdReturnTopParent(configVo.getId());

        List<IsfdBusinessDatabaseRefWithNameVo> refWithNameVos = isfdBusinessDatabaseRefMapper.getAllDataWithNames(null, null, Collections.singletonList(topConfig.getId()), null);

        if (CollectionUtils.isEmpty(refWithNameVos)) {
            throw new BaseException("没有找到模型的场景/库关联关系, modelId: " + configVo.getId());
        }
        IsfdBusinessDatabaseRefWithNameVo refWithNameVo = refWithNameVos.get(0);

        Integer mainTableDataQuantity = tableNameAndDataQuantity.get(mainTableName);
        if (mainTableDataQuantity == null) {
            throw new BaseException("没有找到主表数据: " + mainTableName);
        }

        // 生成记录
        recordBo.setImportMethod(importMethodEnum.getDesc());
        recordBo.setDataQuantity(mainTableDataQuantity);
        recordBo.setTableName(String.join(",", tableNameAndDataQuantity.keySet()));
        recordBo.setDataImportTime(new DateTime());
        if (loginUser != null) {
            recordBo.setDataImportBy(loginUser.getUserId().toString());
            recordBo.setCreateBy(loginUser.getUserId());
            recordBo.setUpdateBy(loginUser.getUserId());
            recordBo.setCreateDept(loginUser.getDeptId());
            if (recordBo.getDataOwnerId() == null) {
                recordBo.setDataOwnerId(loginUser.getUserId().toString());
                recordBo.setDataOwnerName(loginUser.getNickname());
            }
        }

        recordBo.setCreateTime(new DateTime());

        recordBo.setUpdateTime(new DateTime());


        recordBo.setModelId(refWithNameVo.getParentModelId());
        recordBo.setModelName(refWithNameVo.getModelName());
        recordBo.setBusinessDatabaseRefId(refWithNameVo.getId());
        recordBo.setDatabaseTypeId(refWithNameVo.getDatabaseTypeId());
        recordBo.setDatabaseTypeName(refWithNameVo.getModelName());
        recordBo.setSceneId(refWithNameVo.getSceneId());
        recordBo.setSceneName(refWithNameVo.getSceneName());
        recordBo.setSystemId(refWithNameVo.getSystemId());
        recordBo.setSystemName(refWithNameVo.getSystemName());



        if (StringUtils.isBlank(recordBo.getDataSafeLevel())) {
            recordBo.setDataSafeLevel("high");
        }

        if (StringUtils.isBlank(recordBo.getDataRetentionPolicy())) {
            recordBo.setDataRetentionPolicy("forever");
        }



        insertByBo(recordBo);
        if (recordBo.getId() == null) {
            throw new BaseException("数据导入记录生成失败！");
        }

        for (String tableName : tableNameAndDataQuantity.keySet()) {
            Integer dataCount = tableNameAndDataQuantity.get(tableName);
            updateOrCreateImportSubRecord(recordBo.getId(), tableName, dataCount, 0, 0);
        }

        return recordBo;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void updateOrCreateImportSubRecord(Long recordId, String tableName, Integer createdCount, Integer deletedCount, Integer existedCount) {

        IsfdDatabaseDataImportSubRecordBo subRecordBo = checkAndUpdateSubRecord(recordId, tableName);

        if (subRecordBo.getImportQuantity().equals(0)){
            subRecordBo.setImportQuantity(existedCount);
        }

        if (subRecordBo.getId() == null) {
            importSubRecordService.insertByBo(subRecordBo);
        }

        Integer importQuantity = Optional.ofNullable(subRecordBo.getImportQuantity()).orElse(0);
        Integer deleteQuantity = Optional.ofNullable(subRecordBo.getDeleteQuantity()).orElse(0);
        subRecordBo.setImportQuantity(importQuantity + createdCount);
        subRecordBo.setDeleteQuantity(deleteQuantity + deletedCount);
        importSubRecordService.updateByBo(subRecordBo);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public IsfdDatabaseDataImportSubRecordBo checkAndUpdateSubRecord(Long recordId, String tableName){
        // 查询子记录
        IsfdDatabaseDataImportSubRecord subRecord = importSubRecordService.findByRecordIdAndTableName(recordId, tableName);

        if (subRecord == null) {
            // 查询库内实际数据量
            Long existDataCountL = countMongoDataByImportId(recordId, tableName, false);
            Integer existDataCount = existDataCountL == null ? 0 : existDataCountL.intValue();

            Long deletedDataCountL = countMongoDataByImportId(recordId, tableName, true);
            Integer deletedDataCount = deletedDataCountL == null ? 0 : deletedDataCountL.intValue();
            // 创建新记录
            subRecord = new IsfdDatabaseDataImportSubRecord();
            subRecord.setImportRecordId(recordId);
            subRecord.setTableName(tableName);
            subRecord.setImportQuantity(existDataCount);
            subRecord.setDeleteQuantity(deletedDataCount);

            // 可根据实际情况设置其他必填字段
            IsfdDatabaseDataImportSubRecordBo createBo = MapstructUtils.convert(subRecord, IsfdDatabaseDataImportSubRecordBo.class);
            return createBo;
        }

        Integer createdCount = subRecord.getImportQuantity();
        Integer deletedCount = subRecord.getDeleteQuantity();

        if (createdCount >= deletedCount) {
            return MapstructUtils.convert(subRecord, IsfdDatabaseDataImportSubRecordBo.class);
        }

        // 重新获取实际新增数
        Long existDataCountL = countMongoDataByImportId(recordId, tableName, false);
        createdCount = existDataCountL == null ? 0 : existDataCountL.intValue();

        if (createdCount < deletedCount) {
            String message = String.format("子记录表[%s]中删除数量大于新增数量，请检查数据记录，recordId=%d，新增数量=%d，删除数量=%d", tableName, recordId, createdCount, deletedCount);
            log.error(message);
            throw new BaseException(message);
        }

        subRecord.setImportQuantity(createdCount);
        IsfdDatabaseDataImportSubRecordBo createBo = MapstructUtils.convert(subRecord, IsfdDatabaseDataImportSubRecordBo.class);
        importSubRecordService.updateByBo(createBo);

        return createBo;
    }

    @Override
    public Long countMongoDataByImportId(Long recordId, String tableName, Boolean isDelete) {
        // 总量
        IsfdDatabaseMongoQuery countCondition = new IsfdDatabaseMongoQuery();
        //
        IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition importRecordIdQuery = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
        importRecordIdQuery.setFieldName(IsfdDatabaseModelSpecialFieldNameEnum.IMPORT_METHOD.getValue() + "." + "id");
        importRecordIdQuery.setOperator("eq");
        importRecordIdQuery.setValue(recordId.toString());
        importRecordIdQuery.setValueNumberCheck(true);
        // 增加逻辑删除筛选
        IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition logicalDeleteQuery = new IsfdDatabaseMongoQuery.IsfdDatabaseMongoQueryCondition();
        logicalDeleteQuery.setFieldName(IsfdDatabaseModelSpecialFieldNameEnum.IMPORT_METHOD.getValue() + "." + "delete_flag");
        logicalDeleteQuery.setOperator("eq");
        logicalDeleteQuery.setValue(isDelete? "1" : "0" );

        countCondition.setConditions(new ArrayList<>());
        countCondition.getConditions().add(importRecordIdQuery);
        countCondition.getConditions().add(logicalDeleteQuery);
        return mongoService.count(tableName, countCondition);
    }

    @Override
    public Integer getRealCountByCondition(Long recordId, String tableName) {
        List<IsfdDatabaseDataImportSubRecord> subRecordList = isfdDatabaseDataImportSubRecordMapper.selectList(new LambdaQueryWrapper<IsfdDatabaseDataImportSubRecord>()
            .eq(recordId != null, IsfdDatabaseDataImportSubRecord::getImportRecordId, recordId)
            .eq(StringUtils.isNotBlank(tableName), IsfdDatabaseDataImportSubRecord::getTableName, tableName));
        if (CollectionUtils.isEmpty(subRecordList)) {
            return 0;
        }
        int result = 0;
        for (IsfdDatabaseDataImportSubRecord subRecord : subRecordList) {
            Integer importQuantity = subRecord.getImportQuantity();
            Integer deleteQuantity = subRecord.getDeleteQuantity();
            result = result + (importQuantity - deleteQuantity);
        }
        return result;
    }
}
